//
//  LoginViewController.m
//  FuelLog
//
//  Created by Pure Mass Communications on 2/22/09.
//  Copyright 2009 . All rights reserved.
//
//  Placed under GPL v2 with the kind permission of Pure Mass Communications
//
//  Modified to make compile under SDK 3.1 by Olaf Greck in May 2010
//
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.

//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.

//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

// requires gdata 1.7 or less. 

#define _UserAgentIdString @"FuelLog-Free-3.3"
#import <Security/Security.h>

#import "LoginViewController.h"
#import "FuelLogAppDelegate.h"
#import "FuelLogViewController.h"
#import "CarsViewController.h"
#import "AddCarViewController.h"
#import "FilesViewController.h"
#import "DebugOutput.h"

#import "DebugOutput.h"
@interface LoginViewController (PrivateMethods)
- (void)findFuelLogFolder;
- (void)findFolderTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object;
- (void)findFolderTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error;

- (void)makeFuelLogFolder:(GDataFeedDocList *)list;
- (void)makeFolderTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object;
- (void)makeFolderTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error;

- (void)findFuelLogFiles;
- (void)findFilesTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object;
- (void)findFilesTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error;

- (void)exportCar;
- (void)exportCarTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object;
- (void)exportCarTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error;

- (GDataServiceGoogleSpreadsheet *)spreadsheetService;
- (GDataServiceGoogleDocs *)docsService;

- (void)alertBegin;
- (void)alertSuccess;
- (void)alertFail:(NSString *)error;
@end

@implementation LoginViewController

@synthesize mode, car;
@synthesize loginButton;


// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
debug(@"in initWithNibName");
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
		debug(@"in super");
        // Custom initialization
#if TARGET_IPHONE_SIMULATOR
		pwWrapper = nil;
#else
		pwWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"Google Password" accessGroup:@"G2RGU5XQDB.com.olafgreck.fuellogevo"];
#endif
#pragma mark Edit accessGroup above xxx olaf xxx
		alertView = nil;
		spreadsheetService = nil;
		docService = nil;
		ticket = nil;
		cancelled = NO;
    }
    return self;
}

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
	debug(@"in viewDidLoad");
    [super viewDidLoad];
    FuelLogAppDelegate *appDelegate = (FuelLogAppDelegate *)[[UIApplication sharedApplication] delegate];
	if (pwWrapper != nil) {
		NSString *uname = [pwWrapper objectForKey:(id)kSecAttrAccount];
		NSString *pw = [pwWrapper objectForKey:(id)kSecValueData];
		[appDelegate setUsername:uname];
		[appDelegate setPassword:pw];
	}
	[usernameBox setText:[appDelegate username]];
	[passwordBox setText:[appDelegate password]];
	usernameBox.clearButtonMode = UITextFieldViewModeWhileEditing;
	passwordBox.clearButtonMode = UITextFieldViewModeWhileEditing;
	if (mode == FUELLOG_IMPORT) {
		[loginButton setTitle:(NSLocalizedString(@"Login_viewDidLoad Login",@"Login")) forState:UIControlStateNormal];
	} else {
		[loginButton setTitle:(NSLocalizedString(@"Login_viewDidLoad Export",@"Export")) forState:UIControlStateNormal];
	}
	[self.loginButton useSystemTouchStyle];	
}

- (void)viewWillAppear:(BOOL)animated {
	debug(@"in viewWillAppear:(BOOL)animated");
	if (mode == FUELLOG_IMPORT) {
		[loginButton setTitle:(NSLocalizedString(@"Login_viewWillAppear Login",@"Login")) forState:UIControlStateNormal];
	} else {
		[loginButton setTitle:(NSLocalizedString(@"Login_viewWillAppear Export",@"Export")) forState:UIControlStateNormal];
	}
}
 

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}


- (void)dealloc {
	if (docService) {
		[docService dealloc];
		docService = nil;
	}
	if (spreadsheetService) {
		[spreadsheetService dealloc];
		spreadsheetService = nil;
	}
	if (alertView) {
		[alertView dealloc];
		alertView = nil;
	}
	if (pwWrapper) {
		[pwWrapper dealloc];
		pwWrapper = nil;
	}
	[loginButton release];
    [super dealloc];
}

- (IBAction)login:(id)sender {
	creatingFolder = NO;
	if (pwWrapper != nil) {
		if (saveSwitch.on) {
			[pwWrapper setObject:usernameBox.text forKey:(id)kSecAttrAccount];
			[pwWrapper setObject:passwordBox.text forKey:(id)kSecValueData];			
		} else {
			[pwWrapper resetKeychainItem];	
		}
	}
	[self findFuelLogFolder];
}

- (IBAction)cancel:(id)sender {
	debug(@"in cancel");
	[usernameBox resignFirstResponder];
	[passwordBox resignFirstResponder];
	[self dismissModalViewControllerAnimated:YES];
	if (mode == FUELLOG_IMPORT) {
	FilesViewController *fvc = (FilesViewController *)self.parentViewController;
		CarsViewController *cvc = (CarsViewController *)fvc.parentViewController;
		[cvc clickSelectedCar];
		[fvc setCancelled:YES];
		 
	}
}

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
	NSString *user = [usernameBox.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
	if ([user rangeOfString:@"@"].location == NSNotFound) {
		user = [user stringByAppendingString:@"@gmail.com"];
	}
	[usernameBox setText:user];
	NSString *pw = [passwordBox.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
	[passwordBox setText:pw];
	[theTextField resignFirstResponder];
	return YES;
}

- (GDataServiceGoogleSpreadsheet *)spreadsheetService {	
	if (!spreadsheetService) {
		spreadsheetService = [[GDataServiceGoogleSpreadsheet alloc] init];		
		[spreadsheetService setUserAgent:_UserAgentIdString];
#pragma mark Edit userAgent above xxx olaf xxx
		[spreadsheetService setShouldCacheDatedData:YES];
		[spreadsheetService setShouldServiceFeedsIgnoreUnknowns:YES];
		[spreadsheetService setServiceShouldFollowNextLinks:YES];
	}
	
	// username/password may change
	NSString *username = usernameBox.text;
	NSString *password = passwordBox.text;	
	[spreadsheetService setUserCredentialsWithUsername:username password:password];
	return spreadsheetService;
}

- (GDataServiceGoogleDocs *)docsService {	
	if (!docService) {
		docService = [[GDataServiceGoogleDocs alloc] init];		
		[docService setUserAgent:_UserAgentIdString];
#pragma mark Edit userAgent above xxx olaf xxx
		[docService setShouldCacheDatedData:NO];
		[docService setShouldServiceFeedsIgnoreUnknowns:YES];		
		[docService setServiceShouldFollowNextLinks:YES];
	}
	
	// username/password may change
	NSString *username = usernameBox.text;
	NSString *password = passwordBox.text;	
	[docService setUserCredentialsWithUsername:username password:password];
	return docService;
}

- (void)findFuelLogFolder {
	success = YES;
	cancelled = NO;
	GDataServiceGoogleDocs *service = [self docsService];
	
	NSURL *feedURL = [NSURL URLWithString:kGDataGoogleDocsDefaultPrivateFullFeed];
	
	GDataQueryDocs *query = [GDataQueryDocs documentQueryWithFeedURL:feedURL];
	[query setTitleQuery:@"Fuel Log"];
	[query setIsTitleQueryExact:YES];
	[query setMaxResults:1];
	[query setShouldShowFolders:YES];
	
	ticket = [service fetchDocsQuery:query
							delegate:self
				   didFinishSelector:@selector(findFolderTicket:finishedWithFeed:)
					 didFailSelector:@selector(findFolderTicket:failedWithError:)];
	[self alertBegin];
}

- (void)findFolderTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object {
	if (cancelled) {
		return;
	}
	GDataFeedDocList *list = (GDataFeedDocList *) object;
	NSArray *entries = [list entries];
	if ([entries count] > 0) {
		creatingFolder = NO;
		folder = (GDataEntryFolderDoc *)[entries objectAtIndex:0];
		[self findFuelLogFiles];
	} else if (creatingFolder) {
		creatingFolder = NO;
		[self alertFail:(NSLocalizedString(@"Login_findFolderTicket_finishedWithFeed folder deleted while retrieving",@"Fuel Log folder was deleted while retrieving it.")) ];
	} else {
		creatingFolder = YES;
		[self makeFuelLogFolder:list];
	}
} 

- (void)findFolderTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error {
	success = NO;
	[self alertFail:(NSLocalizedString(@"Login_findFolderTicket_failedWithError Failed to connect, check blah",@"Failed to connect to Google. Please make sure your iPhone has Internet connection. Check your username and password.")) ];
}

- (void)makeFuelLogFolder:(GDataFeedDocList *)list {
	if (cancelled) {
		return;
	}
	GDataServiceGoogleDocs *service = [self docsService];
	NSURL *postURL = [[list postLink] URL];
	
	if (!postURL) {
		[self alertFail:(NSLocalizedString( @"Login_makeFuelLogFolder incomplete data", @"Received incomplete data from Google."))];
		return;
	}
	
	GDataEntryFolderDoc *fuellogFolder = [GDataEntryFolderDoc documentEntry];
	GDataCategory *category = [GDataCategory 
							   categoryWithScheme:kGDataCategoryScheme 
							   term:kGDataCategoryFolderDoc]; 
	[fuellogFolder setCategories:[NSArray arrayWithObject:category]]; 
	[category setLabel:@"folder"]; 
	[fuellogFolder setTitleWithString:@"Fuel Log"]; 	 
	
	ticket = [service fetchDocEntryByInsertingEntry:fuellogFolder
										 forFeedURL:postURL 
										   delegate:self 
								  didFinishSelector:@selector(makeFolderTicket:finishedWithFeed:)
									didFailSelector:@selector(makeFolderTicket:failedWithError:)];
}

- (void)makeFolderTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object {
	if (cancelled) {
		return;
	}
	[self findFuelLogFolder];
} 

- (void)makeFolderTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error {
	success = NO;
	[self alertFail:(NSLocalizedString(@"Login_makeFolderTicket_failedWithError Cannot create folder.",@"Cannot create Fuel Log folder.")) ];
}

- (void)findFuelLogFiles {
	if (cancelled) {
		return;
	}
	GDataServiceGoogleDocs *service = [self docsService];

	// selfLink is wrong; feedLink is nil
	// NSURL *feedURL = [[folder selfLink] URL];
	NSString *feedURI = [[folder content] sourceURI]; 
	if (feedURI == nil) {
		[self alertFail:(NSLocalizedString(@"Login_findFuelLogFiles folder exists but cannot opened.",@"Fuel Log folder exists but cannot be opened.")) ];
		return;
	}
	NSURL *feedURL = [NSURL URLWithString:feedURI]; 
	
	GDataQueryDocs *query = [GDataQueryDocs documentQueryWithFeedURL:feedURL];
	[query setMaxResults:65535];
	[query setShouldShowFolders:NO];
    
	ticket = [service fetchDocsQuery:query
							delegate:self
				   didFinishSelector:@selector(findFilesTicket:finishedWithFeed:)
					 didFailSelector:@selector(findFilesTicket:failedWithError:)];
}

- (void)findFilesTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object {
	debug(@"in findFilesTicket");
	if (cancelled) {
		return;
	}
	GDataFeedDocList *list = (GDataFeedDocList *) object;
	folderPostURL = [[list postLink] URL];
	if (!folderPostURL) {
		[self alertFail:(NSLocalizedString(@"Login_findFilesTicket_finishedWithFeed incomplete data",@"Received incomplete data from Google.")) ];
		return;
	}
	
	files = [list entries];
	int max = -1;
	if (car != nil && mode == FUELLOG_EXPORT) {
		for (int i = 0; i < [files count]; ++i) {
			GDataEntryDocBase *doc = (GDataEntryDocBase *)[files objectAtIndex:i];
			NSString *title = [[doc title] stringValue];
			NSRange where = [title rangeOfString:car.label];
			if (where.location == 0) {
				if ([title length] <= [car.label length] + 1) {
					if (max < 0) {
						max = 0;
					}
				} else {
					NSString *suffix = [title substringFromIndex:([car.label length] + 1)];
					int c = [suffix intValue];
					if (c > max) {
						max = c;
					}
				}
			}
		}
		if (max == -1) {
			filename = [car.label copy];
		} else {
			filename = [NSString stringWithFormat:@"%@_%d", car.label, (max + 1)];
		}
		[self exportCar];
	} else if (mode == FUELLOG_IMPORT) {
		FilesViewController *fvc = [FuelLogViewController filesViewController];
		[fvc setReady:YES];
		[fvc setFiles:files];
		[fvc setService:[self docsService]];
		[fvc setSpreadsheetService:[self spreadsheetService]];
		[fvc resetData];
		[alertView dismissWithClickedButtonIndex:-1	animated:YES];
		[self dismissModalViewControllerAnimated:YES];
		debug(@"dismissing loginViewController here");
		 
	}
} 

// failed
- (void)findFilesTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error {
	success = NO;
	[self alertFail:(NSLocalizedString(@"Login_findFilesTicket_failedWithError Failed to access folder",@"Failed to access Fuel Log folder. Did you delete it using another computer?")) ];
}

- (void)exportCar {
	if (cancelled) {
		return;
	}
    FuelLogAppDelegate *appDelegate = (FuelLogAppDelegate *)[[UIApplication sharedApplication] delegate];
	Car *currentCar = appDelegate.currentCar;
	[appDelegate chooseCar:car];
	NSMutableData *data = [NSMutableData dataWithBytes:[Gas exportHeader] length:[Gas exportHeaderLen]];
	NSDateFormatter *formatter = [appDelegate defaultDateFormatter];
	for (int i = [appDelegate.pumps count] - 1; i >= 0; --i) {
		Gas *gas = (Gas *)[appDelegate.pumps objectAtIndex:i];
		const char *bytes = [gas exportCString:formatter];
		[data appendBytes:bytes	length:strlen(bytes)];
	}
	[appDelegate chooseCar:currentCar]; 
	
	GDataServiceGoogleDocs *service = [self docsService];
	
	GDataEntryDocBase *docEntry = [GDataEntryStandardDoc documentEntry]; 
	[docEntry setTitleWithString:filename]; 
	[docEntry setUploadData:data]; 
	[docEntry setUploadMIMEType:@"text/csv"]; 
	[docEntry setUploadSlug:filename]; 
	
	ticket = [service fetchDocEntryByInsertingEntry:docEntry 
										 forFeedURL:folderPostURL
										   delegate:self 
								  didFinishSelector:@selector(exportCarTicket:finishedWithFeed:) 
									didFailSelector:@selector(exportCarTicket:failedWithError:)]; 
}

- (void)exportCarTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataEntryDocBase *)object {
	[self alertSuccess];
} 

- (void)exportCarTicket:(GDataServiceTicket *)ticket failedWithError:(NSError *)error {
	success = NO;
	[self alertFail:(NSLocalizedString(@"Login_exportCarTicket_failedWithError No upload, retry ",@"Unable to upload data to Google. Please try again.")) ];
}

#pragma mark UIAlertView

- (void)alertBegin {
	[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
//	[alertView setBackgroundColor:[UIColor blueColor] withStrokeColor:[UIColor greenColor]];
	NSString *msg = nil;
	if (mode == FUELLOG_IMPORT) {
		msg = (NSLocalizedString(@"Login_alertBegin Looking for imports",@"Looking for files to import from your Fuel Log folder..."));
	} else {
		msg = [NSString stringWithFormat:(NSLocalizedString(@"Login_alertBegin Exporting xxx",@"Exporting %@ to your Fuel Log folder...")), car.label];
	}
	if (alertView) {
		alertView.message = msg;	
	} else {
		alertView = [[UIAlertView alloc] initWithTitle:@"" 
											   message:msg
											  delegate:self 
									 cancelButtonTitle:(NSLocalizedString(@"Login_alertBegin Cancel" ,@"Cancel" ))
									 otherButtonTitles:nil];
	}
	[alertView show];
}

- (void)alertSuccess {
	[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
	// open a alert with an OK
	if (alertView) {
		[alertView dismissWithClickedButtonIndex:-1 animated:YES];
	}
	NSString *msg = [NSString stringWithFormat:(NSLocalizedString(@"Login_alertSuccess Exported xx as yy",@"Exported %@ as %@ in your Fuel Log folder")), car.label, filename];
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" 
													message:msg
												   delegate:self 
										  cancelButtonTitle:(NSLocalizedString(@"Login_alertSuccess OK",@"OK")) 
										  otherButtonTitles:nil];
	[alert show];
	[alert release];
}

- (void)alertFail:(NSString *)error {
	// open a alert with an OK
	if (alertView) {
		[alertView dismissWithClickedButtonIndex:-1 animated:YES];
	}
	NSString *directionOfTransaction = (NSLocalizedString(@"Login_alertFail Exporting failed",@"Exporting failed"));
	if (mode == FUELLOG_IMPORT) {
		directionOfTransaction = (NSLocalizedString(@"Login_alertFail Importing failed",@"Importing failed"));
	}
	NSString *messageToDisplay = [NSString stringWithFormat:@"%@\n%@ %@ ", directionOfTransaction, (car ? car.label : @""), error];
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" 
													message:messageToDisplay
												   delegate:self 
										  cancelButtonTitle:(NSLocalizedString(@"Login_alertFail OK",@"OK")) 
										  otherButtonTitles:nil];
	[alert show];
	[alert release];
}

#pragma mark UIAlertViewDelegate

- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
	[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
	if (buttonIndex == [alert cancelButtonIndex]) {
		if (alert == alertView) {
			cancelled = YES;
			if (ticket) {
				[ticket cancelTicket];
			}
		} else if (success) {
			[self cancel:self];
		}
	}
}

@end
